<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <title>FreeMarker-模板开发笔记 | 净土</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="FreeMarker;Java模板引擎;模板开发">
<meta property="og:type" content="article">
<meta property="og:title" content="FreeMarker-模板开发笔记">
<meta property="og:url" content="http://howiefh.github.io/2015/04/30/freemarker-template-development-note/index.html">
<meta property="og:site_name" content="净土">
<meta property="og:description" content="FreeMarker;Java模板引擎;模板开发">
<meta property="og:updated_time" content="2015-05-21T15:56:43.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="FreeMarker-模板开发笔记">
<meta name="twitter:description" content="FreeMarker;Java模板引擎;模板开发">
  
    <link rel="alternative" href="/atom.xml" title="净土" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.ico">
  
  <link href="http://fonts.useso.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  <link rel="stylesheet" href="/css/style.css" type="text/css">
  
<script type="text/javascript">
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-40492061-1', 'auto');
ga('send', 'pageview');

</script>


  
<script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "//hm.baidu.com/hm.js?56d2899c5e919fbf4a7b00de5d1c31dd";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script>


</head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">净土</a>
      </h1>
      
        <h2 id="subtitle-wrap">
          <a href="/" id="subtitle">乐不在外而在心，心以为乐，则是境皆乐；心以为苦，则无境不苦。</a>
        </h2>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-github-link" class="nav-icon" href="https://github.com/howiefh" title="Github" target="_blank"></a>
        
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed" target="_blank"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" results="0" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://howiefh.github.io"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main"><article id="post-freemarker-template-development-note" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    
<a href="/2015/04/30/freemarker-template-development-note/" class="article-date">
  <time datetime="2015-04-30T01:19:31.000Z" itemprop="datePublished">2015-04-30</time>
</a>


    
  <div class="article-category">
    <a class="article-category-link" href="/categories/Java/">Java</a>►<a class="article-category-link" href="/categories/Java/FreeMarker/">FreeMarker</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      FreeMarker-模板开发笔记
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
		
		<div id="toc" class="toc-article">
			<h2 class="toc-title"><span>Contents</span></h2>
		
			<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#概览"><span class="toc-number">1.</span> <span class="toc-text">概览</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#if"><span class="toc-number">1.1.</span> <span class="toc-text">if</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#list"><span class="toc-number">1.2.</span> <span class="toc-text">list</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#include"><span class="toc-number">1.3.</span> <span class="toc-text">include</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#数值和类型"><span class="toc-number">2.</span> <span class="toc-text">数值和类型</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#支持的类型"><span class="toc-number">2.1.</span> <span class="toc-text">支持的类型</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#模板"><span class="toc-number">3.</span> <span class="toc-text">模板</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#快速浏览"><span class="toc-number">3.1.</span> <span class="toc-text">快速浏览</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#字符串"><span class="toc-number">3.2.</span> <span class="toc-text">字符串</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#数字"><span class="toc-number">3.3.</span> <span class="toc-text">数字</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#序列"><span class="toc-number">3.4.</span> <span class="toc-text">序列</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#哈希表"><span class="toc-number">3.5.</span> <span class="toc-text">哈希表</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#+、-、*、/、%"><span class="toc-number">3.6.</span> <span class="toc-text">+、-、*、/、%</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#比较"><span class="toc-number">3.7.</span> <span class="toc-text">比较</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#内建函数"><span class="toc-number">4.</span> <span class="toc-text">内建函数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#方法调用"><span class="toc-number">5.</span> <span class="toc-text">方法调用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#处理不存在的变量"><span class="toc-number">6.</span> <span class="toc-text">处理不存在的变量</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#默认值"><span class="toc-number">6.1.</span> <span class="toc-text">默认值</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#插值"><span class="toc-number">7.</span> <span class="toc-text">插值</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#其他"><span class="toc-number">8.</span> <span class="toc-text">其他</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#自定义指令"><span class="toc-number">8.1.</span> <span class="toc-text">自定义指令</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#参数"><span class="toc-number">8.1.1.</span> <span class="toc-text">参数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#嵌套内容"><span class="toc-number">8.1.2.</span> <span class="toc-text">嵌套内容</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#宏和循环变量"><span class="toc-number">8.1.3.</span> <span class="toc-text">宏和循环变量</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#在模板中可以定义三种类型的变量"><span class="toc-number">8.1.4.</span> <span class="toc-text">在模板中可以定义三种类型的变量</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#命名空间"><span class="toc-number">8.2.</span> <span class="toc-text">命名空间</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#创建一个库"><span class="toc-number">8.2.1.</span> <span class="toc-text">创建一个库</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#命名空间和数据模型"><span class="toc-number">8.2.2.</span> <span class="toc-text">命名空间和数据模型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#命名空间的生命周期"><span class="toc-number">8.2.3.</span> <span class="toc-text">命名空间的生命周期</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#编写类库"><span class="toc-number">8.2.4.</span> <span class="toc-text">编写类库</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#空白处理"><span class="toc-number">8.3.</span> <span class="toc-text">空白处理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#替换（方括号）语法"><span class="toc-number">8.4.</span> <span class="toc-text">替换（方括号）语法</span></a></li></ol></li></ol>
		
		</div>
		
        <h2 id="概览">概览</h2><h3 id="if">if</h3><figure class="highlight smalltalk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="class">Welcome</span> <span class="char">$&#123;</span>user&#125;&lt;<span class="symbol">#if</span> user == <span class="comment">"Big Joe"</span>&gt;, our beloved leader&lt;/<span class="symbol">#if</span>&gt;!</span><br></pre></td></tr></table></figure>
<h3 id="list">list</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">#list</span> <span class="attribute">animals</span> <span class="attribute">as</span> <span class="attribute">being</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">tr</span>&gt;</span><span class="tag">&lt;<span class="title">td</span>&gt;</span>$&#123;being.name&#125;<span class="tag">&lt;<span class="title">td</span>&gt;</span>$&#123;being.price&#125; Euros</span><br><span class="line"><span class="tag">&lt;/<span class="title">#list</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="include">include</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;<span class="preprocessor">#<span class="keyword">include</span> "/copyright_footer.html"&gt;</span></span><br></pre></td></tr></table></figure>
<a id="more"></a>
<h2 id="数值和类型">数值和类型</h2><h3 id="支持的类型">支持的类型</h3><ul>
<li>标量：<ul>
<li>字符串</li>
<li>数字</li>
<li>布尔值</li>
<li>日期</li>
</ul>
</li>
<li>容器：<ul>
<li>哈希表</li>
<li>序列</li>
<li>集</li>
</ul>
</li>
<li>子程序：<ul>
<li>方法和函数：方法是来自于数据模型（它们反射了 Java 对象的方法），而函数是定义在模板内的（使用了函数指令-这也是高级主题），但二者可以用同一种方式来使用。内置的方法<code>${avg(6, 10, 20)}</code></li>
<li>用户自定义指令：按经验来说，如果能够实现，请先用自定义指令而不要用函数/方法。 <code>&lt;@box title=&quot;Attention!&quot;&gt; hello &lt;/@box&gt;</code></li>
</ul>
</li>
<li>其它/很少使用：<ul>
<li>节点</li>
</ul>
</li>
</ul>
<h2 id="模板">模板</h2><p>模板（ FTL 编程）是由如下部分混合而成的：</p>
<ul>
<li>Text 文本：文本会照着原样来输出。</li>
<li>Interpolation 插值： 这部分的输出会被计算的值来替换。插值由${和}所分隔（或者#{和}，这种风格已经不建议再使用了）。</li>
<li>FTL tags 标签： FTL 标签和 HTML 标签很相似，但是它们却是给 FreeMarker 的指示， 而且不会打印在输出内容中。</li>
<li>Comments 注释： FTL 的注释和 HTML 的注释也很相似，但它们是由<code>&lt;#--</code>和<code>--&gt;</code>来分隔的。注释会被 FreeMarker 所忽略，更不会在输出内容中显示。</li>
</ul>
<p>FTL 标签不可以在其他 FTL 标签和插值中使用。下面这样写就是错的：<br><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;<span class="id">#if</span> &lt;<span class="id">#include</span> <span class="string">'foo'</span>&gt;=<span class="string">'bar'</span>&gt;...&lt;/#<span class="keyword">if</span>&gt;</span><br></pre></td></tr></table></figure></p>
<p>注释可以放在 FTL 标签和插值中间。<br>插值可以在文本区域和字符串中出现，但是不能在标签中使用<br><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;#if $&#123;isBig&#125;&gt;</span><span class="tag">&lt;/&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>上面的就是错误的，正确的应该这样写<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;<span class="preprocessor">#<span class="keyword">if</span> isBig&gt;&lt;/<span class="keyword">if</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>FreeMarker可以忽略标签、插值内的空格，但是<code>&lt;</code>、<code>&lt;\</code>和指令之间的空格不能忽略</p>
<h3 id="快速浏览">快速浏览</h3><ul>
<li>直接指定值<ul>
<li>字符串： “Foo” 或者 ‘Foo’ 或者 “It’s \”quoted\”” 或者<br>r”C:\raw\string”</li>
<li>数字： 123.45</li>
<li>布尔值： true, false</li>
<li>序列： [“foo”, “bar”, 123.45], 1..100</li>
<li>哈希表： {“name”:”green mouse”, “price”:150}</li>
</ul>
</li>
<li>检索变量<ul>
<li>顶层变量： user</li>
<li>从哈希表中检索数据： user.name, user[“name”]</li>
<li>从序列中检索： products[5]</li>
<li>特殊变量： .main  。 特殊变量是由 FreeMarker 引擎本身定义的，为了使用它们，可以按照如下语法形式来进行： .variable_name。</li>
</ul>
</li>
<li>字符串操作<ul>
<li>插值（ 或连接）： “Hello ${user}!”（或”Free” + “Marker”）</li>
<li>获取一个字符： name[0]</li>
</ul>
</li>
<li>序列操作<ul>
<li>连接： users + [“guest”]</li>
<li>序列切分： products[10..19] 或 products[5..]</li>
</ul>
</li>
<li>哈希表操作<ul>
<li>连接： passwords + {“joe”:”secret42”}</li>
</ul>
</li>
<li>算数运算: (x * 1.5 + 10) / 2 - y % 100</li>
<li>比较运算 ： <code>x == y, x != y, x &lt; y, x &gt; y, x &gt;= y, x &lt;= y, x &amp;lt; y,</code> 等等</li>
<li>逻辑操作： !registered &amp;&amp; (firstVisit || fromEurope)</li>
<li>内建函数： name?upper_case</li>
<li>方法调用： repeat(“What”, 3)</li>
<li>处理不存在的值<ul>
<li>默认值： name!”unknown” 或者(user.name)!”unknown” 或者<br>name! 或者 (user.name)!</li>
<li>检测不存在的值： name?? 或者(user.name)??</li>
</ul>
</li>
<li>运算符的优先级</li>
</ul>
<p>最高优先级运算符:  [subvarName][subStringRange].?(methodParams)<br>一元前缀运算符: +expr -expr !expr<br>乘除法，求模: * / %<br>加减法: + -<br>关系运算符: <code>&lt; &gt; &lt;= &gt;= (相当于: gt, lt, 等)</code><br>相等，不等: == (也可以是: =) !=<br>逻辑与: &amp;&amp;<br>逻辑或: ||<br>数字范围: ..</p>
<h3 id="字符串">字符串</h3><p>可以使用转义字符<code>\\</code>、<code>\&quot;</code>等。一种特殊的字符串就是原生字符串。在原生字符串中，反斜杠和${没有特殊的含义，它们被视为普通的字符。 为了表明字符串是原生字符串，在开始的引号或单引号之前放置字母 r，例如：<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$&#123;<span class="string">r"$&#123;foo&#125;"</span>&#125;</span><br><span class="line">$&#123;<span class="string">r"C:\foo\bar"</span>&#125;</span><br></pre></td></tr></table></figure></p>
<p>将会打印：<br><figure class="highlight mathematica"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$<span class="list">&#123;foo&#125;</span></span><br><span class="line"><span class="keyword">C</span>:\foo\bar</span><br></pre></td></tr></table></figure></p>
<p>连接<br><figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$&#123;<span class="string">"Hello <span class="subst">$&#123;user&#125;</span>!"</span>&#125;</span><br><span class="line">$&#123;<span class="string">"<span class="subst">$&#123;user&#125;</span><span class="subst">$&#123;user&#125;</span><span class="subst">$&#123;user&#125;</span><span class="subst">$&#123;user&#125;</span>"</span>&#125;</span><br></pre></td></tr></table></figure></p>
<p>和<br><figure class="highlight nsis"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$&#123;<span class="string">"Hello "</span> + <span class="literal">user</span> + <span class="string">"!"</span>&#125;</span><br><span class="line">$&#123;<span class="literal">user</span> + <span class="literal">user</span> + <span class="literal">user</span> + <span class="literal">user</span>&#125;</span><br></pre></td></tr></table></figure></p>
<p>效果上是一样的</p>
<p>可以使用${user[0]}获取某个字符，也可以使用${user[2..5]}和${user[2..]}获取子串</p>
<h3 id="数字">数字</h3><p>数值文字 08, +8, 8.00 和 8 是完全相等的，它们都是数字 8。因此${08}, ${+8}, ${8.00}和${8}打印的都是相同的。</p>
<h3 id="序列">序列</h3><figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;#<span class="keyword">list</span> [<span class="string">"winter"</span>, <span class="string">"spring"</span>, <span class="string">"summer"</span>, <span class="string">"autumn"</span>] <span class="keyword">as</span> x&gt;</span><br><span class="line"><span class="label">$&#123;x&#125;</span></span><br><span class="line">&lt;/#<span class="keyword">list</span>&gt;</span><br></pre></td></tr></table></figure>
<p>列表中的项目是表达式，那么也可以这样做： [2 + 2, [1, 2, 3, 4], “whatnot”]，其中第一个子变量是数字 4，第二个子变量是一个序列，第三个子变量是字符串”whatnot”。<br>也可以用 start..end 定义存储数字范围的序列，这里的 start 和 end 是处理数字值表达式，比如 2..5 和[2, 3, 4, 5]是相同的，但是使用前者会更有效率（ 内存占用少而且速度快）。</p>
<p>序列的连接可以使用+号来进行<br><figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;#<span class="keyword">list</span> [<span class="string">"Joe"</span>, <span class="string">"Fred"</span>] + [<span class="string">"Julia"</span>, <span class="string">"Kate"</span>] <span class="keyword">as</span> user&gt;</span><br><span class="line">- <span class="label">$&#123;user&#125;</span></span><br><span class="line">&lt;/#<span class="keyword">list</span>&gt;</span><br></pre></td></tr></table></figure></p>
<p>序列切分<br>使用 [firstindex..lastindex] 可以获取序列中的一部分，这里的firstindex 和lastindex 表达式的结果是数字。</p>
<h3 id="哈希表">哈希表</h3><p>在模板中指定一个哈希表，就可以遍历用逗号分隔开的“键/值”对，把列表放到花括号内。键和值成对出现并以冒号分隔。看这个例子：{“name”:”green mouse”, “price”:150}。注意到名字和值都是表达式，但是用来检索的名字就必须是字符串类型的。</p>
<p>两种方式从哈希表中检索数据:<br><figure class="highlight inform7"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">book.name</span></span><br><span class="line"><span class="title">book["name"]</span></span><br></pre></td></tr></table></figure></p>
<p>哈希表也可以使用+连接，如果有相同键，+后面出现的会覆盖之前的<br><figure class="highlight dust"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag">&lt;<span class="title">#assign</span> <span class="attribute">ages</span> = </span></span><span class="expression">&#123;<span class="string">"Joe"</span>:23, <span class="string">"Fred"</span>:25&#125;</span><span class="xml"><span class="tag"> + </span></span><span class="expression">&#123;<span class="string">"Joe"</span>:30, <span class="string">"Julia"</span>:18&#125;</span><span class="xml"><span class="tag">&gt;</span></span></span><br></pre></td></tr></table></figure></p>
<h3 id="+、-、*、/、%"><code>+</code>、<code>-</code>、<code>*</code>、<code>/</code>、<code>%</code></h3><p>内建函数int可以取出整数部分<code>${(x/2)?int}</code></p>
<h3 id="比较">比较</h3><p>为了避免大于、小于被当做标签处理，可以用圆括号包含表达式<code>&lt;#if (x&gt;y)&gt;&lt;/if&gt;</code>。也可以用lt、<br>lte、gt、gte来比较</p>
<h2 id="内建函数">内建函数</h2><p>内建函数以?形式提供变量的不同形式或者其他信息。</p>
<ul>
<li>字符串使用的内建函数：<ul>
<li>html: 字符串中所有的特殊 HTML 字符都需要用实体引用来代替（比如<code>&lt;</code>代替&lt;）。</li>
<li>cap_first:字符串的第一个字母变为大写形式</li>
<li>lower_case:字符串的小写形式</li>
<li>upper_case:字符串的大写形式</li>
<li>trim:去掉字符串首尾的空格</li>
</ul>
</li>
<li>序列使用的内建函数：<ul>
<li>size：序列中元素的个数</li>
</ul>
</li>
<li>数字使用的内建函数：<ul>
<li>int:数字的整数部分（比如-1.9?int 就是-1）</li>
</ul>
</li>
</ul>
<h2 id="方法调用">方法调用</h2><ul>
<li>avg求均值</li>
<li>repeat重复输出3次What<figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$&#123;</span>repeat(<span class="string">"What"</span>, <span class="number">3</span>)&#125;</span><br><span class="line"><span class="variable">$&#123;</span>avg(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>)&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="处理不存在的变量">处理不存在的变量</h2><p>一个不存在的变量和一个是 null 的变量， 对于 FreeMarker 来说是一样的，所以这里所指的丢失包含这两种情况。<br>就像下面的例子，当 user 从数据模型中丢失时，模板将会将user 的值表示为字符串”Anonymous”。（若 user 并没有丢失，那么模板就会表现<br>出”Anonymous”不存在一样）：<br><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">&lt;h1&gt;</span>Welcome $&#123;<span class="keyword">user</span>!<span class="string">"Anonymous"</span>&#125;!<span class="variable">&lt;/h1&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>当然也可以在变量名后面通过放置??来询问 FreeMarker 一个变量是否存在。 将它和 if 指令合并，那么如果 user 变量不存在的话将会忽略整个问候代码段：<br><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">&lt;#if user??&gt;</span><span class="variable">&lt;h1&gt;</span>Welcome $&#123;<span class="keyword">user</span>&#125;!<span class="variable">&lt;/h1&gt;</span><span class="variable">&lt;/#if&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>关于多级访问的变量，比 如 animals.python.price，书写代码：animals.python.price!0，仅当 animals.python 存在而仅仅最后一个子变量 price 可能不存在（这种情况下我们假设价格是 0）。 如果 animals 或者 python<br>不存在，那么模板处理过程将会以“未定义的变量”错误而停止。为了防止这种情况的发生，可以这样来书写代码(animals.python.price)!0。这种情况下当 animals 或<br>python 不存在时表达式的结果仍然是 0。 对于??也是同样用来的处理这种逻辑的</p>
<h3 id="默认值">默认值</h3><p>使用形式概览：unsafe_expr!default_expr 或 unsafe_expr! 或 (unsafe_expr)!default_expr 或(unsafe_expr)!</p>
<p>hits!0 或 colors![“red”, “green”, “blue”]</p>
<p>由于 FreeMarker 2.3.x 版本的源码中的小失误所以必须这么来做。 !（作为默认值操作）的优先级非常低。 这就意味着${x!1 + y}会被 FreeMarker 误解为${x!(1 + y)}，而真实的意义是${(x!1) + y}。 这个源码的错误在 FreeMarker 2.4 中会得到修正。</p>
<h2 id="插值">插值</h2><p>字符串<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">#escape</span> <span class="attribute">x</span> <span class="attribute">as</span> <span class="attribute">x</span>?<span class="attribute">html</span>&gt;</span></span><br><span class="line">...</span><br><span class="line"><span class="tag">&lt;<span class="title">p</span>&gt;</span>Title: $&#123;book.title&#125;<span class="tag">&lt;/<span class="title">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">p</span>&gt;</span>Description:</span><br><span class="line"><span class="tag">&lt;<span class="title">#noescape</span>&gt;</span>$&#123;book.description&#125;<span class="tag">&lt;/<span class="title">#noescape</span>&gt;</span><span class="tag">&lt;/<span class="title">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">h2</span>&gt;</span>Comments:<span class="tag">&lt;/<span class="title">h2</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">#list</span> <span class="attribute">comments</span> <span class="attribute">as</span> <span class="attribute">comment</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">div</span> <span class="attribute">class</span>=<span class="value">"comment"</span>&gt;</span></span><br><span class="line">$&#123;comment&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="title">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">#list</span>&gt;</span></span><br><span class="line">...</span><br><span class="line"><span class="tag">&lt;/<span class="title">#escape</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>如果插值在文本区 （也就是说，不再字符串表达式中）， 如果 escapse 指令起作用了，即将被插入的字符串会被自动转义（将&amp;转为&amp;）。如果你要生成 HTML，那么强烈建议你利用它来阻止跨站脚本攻击和非格式良好的 HTML 页面。使用 noescape 可以抵消 escape 的转义。如果你想把所有的输出为大写的话可以x.upper_case</p>
<p>数字</p>
<p>小数的分隔符是根据所在地的标准确定的，如匈牙利的分隔符是<code>,</code>。那么<code>{1.5}</code>会输出<code>1,5</code></p>
<p>可以通过string内置函数来设置输出的格式。</p>
<h2 id="其他">其他</h2><h3 id="自定义指令">自定义指令</h3><p>自定义指令可以使用 macro 指令来定义，这是模板设计者所关心的内容。 Java 程序员若不想在模板中实现定义指令，而是在 Java 语言中实现指令的定义， 这时可以使用freemarker.template.TemplateDirectiveModel 类来扩展</p>
<p>定义宏<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">#macro</span> <span class="attribute">greet</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">font</span> <span class="attribute">size</span>=<span class="value">"+2"</span>&gt;</span>Hello Joe!<span class="tag">&lt;/<span class="title">font</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">#macro</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>使用自定义指令<br><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;@greet&gt;</span><span class="tag">&lt;/@greet&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>或<br><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;@greet/&gt;</span></span><br></pre></td></tr></table></figure></p>
<h4 id="参数">参数</h4><figure class="highlight inform7"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;#macro greet <span class="keyword">person</span>&gt;</span><br><span class="line">&lt;font size=<span class="string">"+2"</span>&gt;Hello $&#123;<span class="keyword">person</span>&#125;!&lt;/font&gt;</span><br><span class="line">&lt;/#macro&gt;</span><br></pre></td></tr></table></figure>
<p>使用<br><figure class="highlight inform7"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;@greet <span class="keyword">person</span>=<span class="string">"Joe"</span>/&gt;</span><br></pre></td></tr></table></figure></p>
<p>输出<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">font</span> <span class="attribute">size</span>=<span class="value">"+2"</span>&gt;</span>Hello Joe!<span class="tag">&lt;/<span class="title">font</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>使用自定义指令提供的参数必须与宏定义的参数对应，如果多于宏定义中的参数则报错；如果少于宏定义中的参数，并且宏中也没有指定有默认值的话，会报错，指定了默认值的话不会报错。</p>
<figure class="highlight inform7"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;#macro greet <span class="keyword">person</span> color=<span class="string">"red"</span>&gt;</span><br><span class="line">&lt;font size=<span class="string">"+2"</span> color=<span class="string">"$&#123;color&#125;"</span>&gt;Hello $&#123;<span class="keyword">person</span>&#125;!&lt;/font&gt;</span><br><span class="line">&lt;/#macro&gt;</span><br></pre></td></tr></table></figure>
<p>使用下面的指令是对的，如果没有color=”red”的话则会报错<br><figure class="highlight inform7"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;@greet <span class="keyword">person</span>=<span class="string">"Joe"</span>/&gt;</span><br></pre></td></tr></table></figure></p>
<p>someParam=foo 和 someParam=”${foo}”是不同的。第一种情况，是把变量 foo 的值作为参数的值来使 用。第二种情况则是使用插值形式的字符串，那么参数值就是字符串了</p>
<h4 id="嵌套内容">嵌套内容</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">#macro</span> <span class="attribute">border</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">table</span> <span class="attribute">border</span>=<span class="value">4</span> <span class="attribute">cellspacing</span>=<span class="value">0</span> <span class="attribute">cellpadding</span>=<span class="value">4</span>&gt;</span><span class="tag">&lt;<span class="title">tr</span>&gt;</span><span class="tag">&lt;<span class="title">td</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">#nested</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">td</span>&gt;</span><span class="tag">&lt;/<span class="title">tr</span>&gt;</span><span class="tag">&lt;/<span class="title">table</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">#macro</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><code>&lt;#nested&gt;</code>指令执行位于开始和结束标记指令之间的模板代码段。<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">@border</span>&gt;</span>The bordered text<span class="tag">&lt;/<span class="title">@border</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>输出<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">table</span> <span class="attribute">border</span>=<span class="value">4</span> <span class="attribute">cellspacing</span>=<span class="value">0</span> <span class="attribute">cellpadding</span>=<span class="value">4</span>&gt;</span><span class="tag">&lt;<span class="title">tr</span>&gt;</span><span class="tag">&lt;<span class="title">td</span>&gt;</span></span><br><span class="line">The bordered text<span class="tag">&lt;/<span class="title">td</span>&gt;</span><span class="tag">&lt;/<span class="title">tr</span>&gt;</span><span class="tag">&lt;/<span class="title">table</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>nested可以多次被调用</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;#macro do_thrice&gt;</span></span><br><span class="line"><span class="tag">&lt;#nested&gt;</span></span><br><span class="line"><span class="tag">&lt;#nested&gt;</span></span><br><span class="line"><span class="tag">&lt;#nested&gt;</span></span><br><span class="line"><span class="tag">&lt;/#macro&gt;</span></span><br><span class="line"><span class="tag">&lt;@do_thrice&gt;</span></span><br><span class="line"><span class="keyword">Anything</span>.</span><br><span class="line"><span class="tag">&lt;/@do_thrice&gt;</span></span><br></pre></td></tr></table></figure>
<p>输出<br><figure class="highlight erlang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">Anything</span>.</span><br><span class="line"><span class="variable">Anything</span>.</span><br><span class="line"><span class="variable">Anything</span>.</span><br></pre></td></tr></table></figure></p>
<p>嵌套的内容可以是任意有效的 FTL，包含其他的用户自定义指令，这样也是对的：<br><figure class="highlight inform7"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;@border&gt;</span><br><span class="line">&lt;ul&gt;</span><br><span class="line">&lt;@do_thrice&gt;</span><br><span class="line">&lt;li&gt;&lt;@greet <span class="keyword">person</span>=<span class="string">"Joe"</span>/&gt;</span><br><span class="line">&lt;/@do_thrice&gt;</span><br><span class="line">&lt;/ul&gt;</span><br><span class="line">&lt;/@border&gt;</span><br></pre></td></tr></table></figure></p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;#<span class="keyword">macro</span> <span class="keyword">repeat</span> <span class="keyword">count</span>&gt;</span><br><span class="line">&lt;#<span class="keyword">local</span> y = <span class="string">"test"</span>&gt;</span><br><span class="line">&lt;#<span class="keyword">list</span> 1..<span class="keyword">count</span> <span class="keyword">as</span> x&gt;</span><br><span class="line"><span class="label">$&#123;y&#125;</span> <span class="label">$&#123;count&#125;</span>/<span class="label">$&#123;x&#125;</span>: &lt;#nested&gt;</span><br><span class="line">&lt;/#<span class="keyword">list</span>&gt;</span><br><span class="line">&lt;/#<span class="keyword">macro</span>&gt;</span><br><span class="line">&lt;@<span class="keyword">repeat</span> <span class="keyword">count</span>=3&gt;<span class="label">$&#123;y</span>!<span class="string">"?"</span>&#125; <span class="label">$&#123;x</span>!<span class="string">"?"</span>&#125; <span class="label">$&#123;count</span>!<span class="string">"?"</span>&#125;&lt;/@<span class="keyword">repeat</span>&gt;</span><br></pre></td></tr></table></figure>
<p>在宏的外部，宏中的局部变量是不可见的</p>
<h4 id="宏和循环变量">宏和循环变量</h4><p>自定义指令也可以有循环变量。比如我们来扩展先前例子中的 do_thrice 指令，就可以拿到当前的循环变量的值。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;<span class="comment">#macro do_thrice&gt;</span></span><br><span class="line">&lt;<span class="comment">#nested 1&gt;</span></span><br><span class="line">&lt;<span class="comment">#nested 2&gt;</span></span><br><span class="line">&lt;<span class="comment">#nested 3&gt;</span></span><br><span class="line">&lt;/<span class="comment">#macro&gt;</span></span><br><span class="line">&lt;@<span class="keyword">do</span>_thrice ; x&gt; &lt;<span class="comment">#-- 用户自定义指令 使用";"代替"as" --&gt;</span></span><br><span class="line"><span class="variable">$&#123;x&#125;</span> Anything.</span><br><span class="line">&lt;/@<span class="keyword">do</span>_thrice&gt;</span><br></pre></td></tr></table></figure>
<p>输出<br><figure class="highlight erlang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> <span class="variable">Anything</span>.</span><br><span class="line"><span class="number">2</span> <span class="variable">Anything</span>.</span><br><span class="line"><span class="number">3</span> <span class="variable">Anything</span>.</span><br></pre></td></tr></table></figure></p>
<p>nested 指令（当然参数可以是任意的表达式）的参数。 循环变量的名称是在自定义指令的开始标记（ <code>&lt;@...&gt;</code>）的参数后面通过分号确定的。</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;#<span class="keyword">macro</span> <span class="keyword">repeat</span> <span class="keyword">count</span>&gt;</span><br><span class="line">&lt;#<span class="keyword">list</span> 1..<span class="keyword">count</span> <span class="keyword">as</span> x&gt;</span><br><span class="line">&lt;#nested x, x/2, x==<span class="keyword">count</span>&gt;</span><br><span class="line">&lt;/#<span class="keyword">list</span>&gt;</span><br><span class="line">&lt;/#<span class="keyword">macro</span>&gt;</span><br><span class="line">&lt;@<span class="keyword">repeat</span> <span class="keyword">count</span>=4 ; c, halfc, last&gt;</span><br><span class="line"><span class="label">$&#123;c&#125;</span>. <span class="label">$&#123;halfc&#125;</span>&lt;#<span class="keyword">if</span> last&gt; Last!&lt;/#<span class="keyword">if</span>&gt;</span><br><span class="line">&lt;/@<span class="keyword">repeat</span>&gt;</span><br></pre></td></tr></table></figure>
<p>如果在分号后面指定了比 nested 指令还多的变量，那么最后的循环变量将不会被创建（在嵌套内容中不会被定义）。如果分号后的指定了比nested指令少的变量，没有问题。</p>
<h4 id="在模板中可以定义三种类型的变量">在模板中可以定义三种类型的变量</h4><ul>
<li>简单变量： 它能从模板中的任何位置来访问，或者从使用 include 指令引入的<br>模板访问。可以使用 assign 或 macro 指令来创建或替换这些变量。</li>
<li>局部变量： 它们只能被设置在宏定义体内，而且只在宏内可见。一个局部变量的生<br>存周期只是宏的调用过程。可以使用 local 指令在宏定义体内创建或替换局部变<br>量。</li>
<li>循环变量：循环变量是由指令（如 list）自动创建的，而且它们只在指令的开始<br>和结束标记内有效。宏的参数是局部变量而不是循环变量。</li>
</ul>
<h3 id="命名空间">命名空间</h3><p>当运行 FTL 模板时，就会有使用 assign 和 macro 指令创建的变量的集合（可能是空的），可以从前一章节来看如何使用它们。像这样的变量集合被称为 namespace 命名空间。在简单的情况下可以只使用一个命名空间，称之为 main namespace 主命名空间。</p>
<h4 id="创建一个库">创建一个库</h4><figure class="highlight lasso"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="subst">&lt;</span><span class="variable">#macro</span> copyright <span class="built_in">date</span><span class="subst">&gt;</span></span><br><span class="line"><span class="subst">&lt;</span>p<span class="subst">&gt;</span>Copyright (C) $&#123;<span class="built_in">date</span>&#125; Julia Smith<span class="built_in">. </span><span class="literal">All</span> rights reserved<span class="built_in">.</span><span class="subst">&lt;</span>/p<span class="subst">&gt;</span></span><br><span class="line"><span class="subst">&lt;</span><span class="subst">/</span><span class="variable">#macro</span><span class="subst">&gt;</span></span><br><span class="line"><span class="subst">&lt;</span><span class="variable">#assign</span> mail <span class="subst">=</span> <span class="string">"jsmith@acme.com"</span><span class="subst">&gt;</span></span><br></pre></td></tr></table></figure>
<p>把上面的这些定义存储在文件 lib/my_test.ftl 中（目录是你存放模板的位置）。假设想在aWebPage.ftl中使用这个模板。如果在aWebPage.ftl 使用<code>&lt;#include &quot;/lib/my_test.ftl&quot;&gt;</code>，那么就会在主命名空间中创建两个变量，所以就不得不使用import 指令来代替 include 了。它会为 lib/my_test.ftl 创建一个空的命名空间，然后在那里执行。在 aWebPage.ftl中就可以用下面的代码。如果在主命名空间中有一个变量，名为 mail 或 copyright， 那么就不会引起混乱了</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;#<span class="literal">import</span> <span class="string">"/lib/my_test.ftl"</span> <span class="literal">as</span> my&gt;</span><br><span class="line">&lt;#-- 被称为<span class="string">"my"</span>的哈希表就会是那个<span class="string">"大门"</span> --&gt;</span><br><span class="line">&lt;<span class="annotation">@my</span>.copyright date=<span class="string">"1999-2002"</span>/&gt;</span><br><span class="line">$&#123;my.mail&#125;</span><br></pre></td></tr></table></figure>
<h4 id="命名空间和数据模型">命名空间和数据模型</h4><p>数据模型中的变量在任何位置都是可见的。数据模型user在lib/my_test.ftl和aWebPage.ftl 都能访问。</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;#macro copyright date&gt;</span></span><br><span class="line"><span class="tag">&lt;p&gt;</span><span class="keyword">Copyright</span> (C) <span class="cbracket">$&#123;date&#125;</span> <span class="cbracket">$&#123;user&#125;</span>. <span class="literal">All</span> rights reserved.&lt;/p&gt;</span><br><span class="line"><span class="tag">&lt;/#macro&gt;</span></span><br><span class="line"><span class="tag">&lt;#assign mail = "$&#123;user&#125;@acme.com"&gt;</span></span><br></pre></td></tr></table></figure>
<p>在模板的命名空间（可以使用 assign 或 macro 指令来创建的变量）中的变量有着比数据模型中的变量更高的优先级，可以覆盖数据模型。如果想在模板中创建任何命名空间都能访问的变量，那么可以使用global指令</p>
<h4 id="命名空间的生命周期">命名空间的生命周期</h4><p>命名空间由使用的 import 指令中所写的路径来识别。如果想多次 import 这个路径，那么只会为第一次的 import 引用创建命名空间执行模板。 后面相同路径的 import 只是创建一个哈希表当作访问相同命名空间的“门”。</p>
<figure class="highlight smalltalk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;<span class="symbol">#import</span> <span class="comment">"/lib/my_test.ftl"</span> as my&gt;</span><br><span class="line">&lt;<span class="symbol">#import</span> <span class="comment">"/lib/my_test.ftl"</span> as foo&gt;</span><br><span class="line">&lt;<span class="symbol">#import</span> <span class="comment">"/lib/my_test.ftl"</span> as bar&gt;</span><br><span class="line"><span class="char">$&#123;</span>my.mail&#125;, <span class="char">$&#123;</span>foo.mail&#125;, <span class="char">$&#123;</span>bar.mail&#125;</span><br><span class="line">&lt;<span class="symbol">#assign</span> mail=<span class="comment">"jsmith@other.com"</span> in my&gt;</span><br><span class="line"><span class="char">$&#123;</span>my.mail&#125;, <span class="char">$&#123;</span>foo.mail&#125;, <span class="char">$&#123;</span>bar.mail&#125;</span><br></pre></td></tr></table></figure>
<p>还要注意命名空间是不分层次的，它们相互之间是独立存在的。那么，如果在命名空间N1 中 import 命名空间 N2，那 N2 也不在 N1 中， N1 只是可以通过哈希表来访问 N2。 这和在主命名空间中 importN2，然后直接访问命名空间 N2 是一样的过程。</p>
<p>每一次模板执行工作都是一个分离且有序的过程，它们仅仅存在一段很短的时间， 同时页面用以呈现内容，然后就和所有填充过的命名空间一起消失了。</p>
<h4 id="编写类库">编写类库</h4><p>命名和Java包命名规范相似，存放路径一般是</p>
<p>/lib/example.sourceforge.net/example.ftl 或<br>/lib/geocities.com/jsmith/example.ftl</p>
<h3 id="空白处理">空白处理</h3><p>FreeMarker 提供下面的工具来处理这个问题：</p>
<ul>
<li>忽略某些模板文件的空白的工具（ 解析阶段空白就被移除了）：<ul>
<li>剥离空白： 这个特性会自动忽略在 FTL 标签周围多余的空白。这个特性可以通过模板来随时使用和禁用。</li>
<li>微调指令： t， rt 和 lt， 使用这些指令可以明确地告诉 FreeMarker 去忽略某些空白。可以阅读参考手册来获取更多信息。</li>
<li>FTL 参数 strip_text：这将从模板中删除所有顶级文本。对模板来说这很有用，它只包含某些定义的宏（还有以他一些没有输出的指令），因为它可以移除宏定义和其他顶级指令中的换行符，这样可以提高模板的可读性。</li>
</ul>
</li>
<li>从输出中移除空白的工具（移除临近的空白）：<ul>
<li>compress 指令</li>
</ul>
</li>
</ul>
<h3 id="替换（方括号）语法">替换（方括号）语法</h3><p>这个特性从 FreeMarker 2.3.4 版本后才可用。<br>FreeMarker 支持一个替换的语法。就是在 FreeMarker 的指令和注释中用[和]来代替<code>&lt;</code>和<code>&gt;</code>，例如下面这个例子：</p>
<ul>
<li>调用预定义指令： [#list animals as being]…[/#list]</li>
<li>调用自定义指令： [@myMacro /]</li>
<li>注释： [#— the comment —]</li>
</ul>
<p>为了使用这种语法从而代替默认语法，从模板开始，使用 ftl 指令都要使用这用语法。[#ftl]</p>
<p>2.4 版本中的默认配置将会自动检测，也就是说第一个 FreeMarker 标签决定了语法形式（它可以是任意的，而不仅仅是 ftl）。</p>

      
    </div>
    <footer class="article-footer">
	  
	  <!-- 百度分享 Start -->
	  <div class="bdsharebuttonbox"><a href="#" class="bds_more" data-cmd="more"></a><a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间"></a><a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博"></a><a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博"></a><a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网"></a><a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信"></a></div>
	  <!-- 百度分享 End -->
	  
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/FreeMarker/">FreeMarker</a></li></ul>

	  
<span>
Updated:<time datetime="2015-05-21T15:56:43.000Z" itemprop="dateModified">2015-05-21</time>
</span>


    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2015/05/02/freemarker-program-development-note/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          FreeMarker-程序开发指南笔记
        
      </div>
    </a>
  
  
    <a href="/2015/04/09/jvm-note-3/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">深入理解Java虚拟机笔记三（JVM性能监控与故障处理工具）</div>
    </a>
  
</nav>

  
</article>



<!-- 多说评论框 start -->

<section id="comments">
  <div class="ds-thread"  data-thread-key="/2015/04/30/freemarker-template-development-note/" data-title="FreeMarker-模板开发笔记" data-url="http://howiefh.github.io/2015/04/30/freemarker-template-development-note/" id="ds_thread">
    <noscript>Please enable JavaScript to view the <a href="//duoshuo.com/?ref_noscript">comments powered by duoshuo.</a></noscript>
  </div>
</section>

<!-- 多说评论框 end -->
</section>
        
          
  <div id="toc" class="toc-aside">
  <h2 class="toc-title">Contents</h2>
    
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#概览"><span class="toc-number">1.</span> <span class="toc-text">概览</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#if"><span class="toc-number">1.1.</span> <span class="toc-text">if</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#list"><span class="toc-number">1.2.</span> <span class="toc-text">list</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#include"><span class="toc-number">1.3.</span> <span class="toc-text">include</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#数值和类型"><span class="toc-number">2.</span> <span class="toc-text">数值和类型</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#支持的类型"><span class="toc-number">2.1.</span> <span class="toc-text">支持的类型</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#模板"><span class="toc-number">3.</span> <span class="toc-text">模板</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#快速浏览"><span class="toc-number">3.1.</span> <span class="toc-text">快速浏览</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#字符串"><span class="toc-number">3.2.</span> <span class="toc-text">字符串</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#数字"><span class="toc-number">3.3.</span> <span class="toc-text">数字</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#序列"><span class="toc-number">3.4.</span> <span class="toc-text">序列</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#哈希表"><span class="toc-number">3.5.</span> <span class="toc-text">哈希表</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#+、-、*、/、%"><span class="toc-number">3.6.</span> <span class="toc-text">+、-、*、/、%</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#比较"><span class="toc-number">3.7.</span> <span class="toc-text">比较</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#内建函数"><span class="toc-number">4.</span> <span class="toc-text">内建函数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#方法调用"><span class="toc-number">5.</span> <span class="toc-text">方法调用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#处理不存在的变量"><span class="toc-number">6.</span> <span class="toc-text">处理不存在的变量</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#默认值"><span class="toc-number">6.1.</span> <span class="toc-text">默认值</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#插值"><span class="toc-number">7.</span> <span class="toc-text">插值</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#其他"><span class="toc-number">8.</span> <span class="toc-text">其他</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#自定义指令"><span class="toc-number">8.1.</span> <span class="toc-text">自定义指令</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#参数"><span class="toc-number">8.1.1.</span> <span class="toc-text">参数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#嵌套内容"><span class="toc-number">8.1.2.</span> <span class="toc-text">嵌套内容</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#宏和循环变量"><span class="toc-number">8.1.3.</span> <span class="toc-text">宏和循环变量</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#在模板中可以定义三种类型的变量"><span class="toc-number">8.1.4.</span> <span class="toc-text">在模板中可以定义三种类型的变量</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#命名空间"><span class="toc-number">8.2.</span> <span class="toc-text">命名空间</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#创建一个库"><span class="toc-number">8.2.1.</span> <span class="toc-text">创建一个库</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#命名空间和数据模型"><span class="toc-number">8.2.2.</span> <span class="toc-text">命名空间和数据模型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#命名空间的生命周期"><span class="toc-number">8.2.3.</span> <span class="toc-text">命名空间的生命周期</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#编写类库"><span class="toc-number">8.2.4.</span> <span class="toc-text">编写类库</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#空白处理"><span class="toc-number">8.3.</span> <span class="toc-text">空白处理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#替换（方括号）语法"><span class="toc-number">8.4.</span> <span class="toc-text">替换（方括号）语法</span></a></li></ol></li></ol>
    
  </div>

<aside id="sidebar">

  
    
<div class="widget-wrap">
  <h3 class="widget-title">ABOUT ME</h3>
  <ul class="widget about-me">
    
    <li><img class="author" title="About me" src="http://fh-1.qiniudn.com/okal-eltocat.jpg" /></li>
    
    
    <li>Hi,I'm FengHao.</li>
    
    <li>I'll share something interesting and my learning experience with you at this blog.</li>
    
    <li>前博客:<a href="http://hi.baidu.com/idea_star" target="_BLANK">百度空间</a></li>
    
  </ul>
</div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Android/">Android</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/C/">C</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Database/">Database</a><span class="category-list-count">13</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/Database/MongoDB/">MongoDB</a><span class="category-list-count">10</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Database/MySQL/">MySQL</a><span class="category-list-count">2</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/categories/Eclipse/">Eclipse</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/FTP/">FTP</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Git/">Git</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Hexo/">Hexo</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Java/">Java</a><span class="category-list-count">20</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/Java/FreeMarker/">FreeMarker</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Java/Shiro/">Shiro</a><span class="category-list-count">2</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/categories/JavaEE/">JavaEE</a><span class="category-list-count">4</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/JavaEE/Hibernate/">Hibernate</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/JavaEE/JSP/">JSP</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/JavaEE/Spring/">Spring</a><span class="category-list-count">2</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/categories/JavaScript/">JavaScript</a><span class="category-list-count">5</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/JavaScript/jQuery/">jQuery</a><span class="category-list-count">1</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/categories/Linux/">Linux</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/PHP/">PHP</a><span class="category-list-count">5</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Suse/">Suse</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Ubuntu/">Ubuntu</a><span class="category-list-count">5</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Vim/">Vim</a><span class="category-list-count">8</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/编程/">编程</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/软件/">软件</a><span class="category-list-count">1</span></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/Android/" style="font-size: 14.75px; color: #65bfa7">Android</a> <a href="/tags/C/" style="font-size: 13.88px; color: #71c1c2">C</a> <a href="/tags/CAS/" style="font-size: 13px; color: #7dc3de">CAS</a> <a href="/tags/Chrome/" style="font-size: 13px; color: #7dc3de">Chrome</a> <a href="/tags/Clean-Code/" style="font-size: 13.88px; color: #71c1c2">Clean Code</a> <a href="/tags/Database/" style="font-size: 13px; color: #7dc3de">Database</a> <a href="/tags/Eclipse/" style="font-size: 13px; color: #7dc3de">Eclipse</a> <a href="/tags/FTP/" style="font-size: 13.88px; color: #71c1c2">FTP</a> <a href="/tags/FreeMarker/" style="font-size: 14.75px; color: #65bfa7">FreeMarker</a> <a href="/tags/Gcc/" style="font-size: 13px; color: #7dc3de">Gcc</a> <a href="/tags/Git/" style="font-size: 14.75px; color: #65bfa7">Git</a> <a href="/tags/Github-Pages/" style="font-size: 13px; color: #7dc3de">Github Pages</a> <a href="/tags/Hexo/" style="font-size: 14.75px; color: #65bfa7">Hexo</a> <a href="/tags/Hibernate/" style="font-size: 13px; color: #7dc3de">Hibernate</a> <a href="/tags/JSP/" style="font-size: 13px; color: #7dc3de">JSP</a> <a href="/tags/JVM/" style="font-size: 14.75px; color: #65bfa7">JVM</a> <a href="/tags/Java/" style="font-size: 14.75px; color: #65bfa7">Java</a> <a href="/tags/JavaMail/" style="font-size: 13px; color: #7dc3de">JavaMail</a> <a href="/tags/JavaScript/" style="font-size: 16.5px; color: #4dbc6f">JavaScript</a> <a href="/tags/Linux/" style="font-size: 13.88px; color: #71c1c2">Linux</a> <a href="/tags/Log/" style="font-size: 13px; color: #7dc3de">Log</a> <a href="/tags/Markdown/" style="font-size: 13.88px; color: #71c1c2">Markdown</a> <a href="/tags/MongoDB/" style="font-size: 20px; color: #1db400">MongoDB</a> <a href="/tags/MySQL/" style="font-size: 13.88px; color: #71c1c2">MySQL</a> <a href="/tags/PHP/" style="font-size: 16.5px; color: #4dbc6f">PHP</a> <a href="/tags/Rhythmbox/" style="font-size: 13px; color: #7dc3de">Rhythmbox</a> <a href="/tags/SSO/" style="font-size: 13px; color: #7dc3de">SSO</a> <a href="/tags/Servlet/" style="font-size: 13px; color: #7dc3de">Servlet</a> <a href="/tags/Shiro/" style="font-size: 13.88px; color: #71c1c2">Shiro</a> <a href="/tags/Spring/" style="font-size: 13.88px; color: #71c1c2">Spring</a> <a href="/tags/Suse/" style="font-size: 13px; color: #7dc3de">Suse</a> <a href="/tags/Thinking-in-Java/" style="font-size: 19.13px; color: #29b61c">Thinking in Java</a> <a href="/tags/Ubuntu/" style="font-size: 17.38px; color: #41ba53">Ubuntu</a> <a href="/tags/Vim/" style="font-size: 18.25px; color: #35b838">Vim</a> <a href="/tags/VirtualBox/" style="font-size: 13px; color: #7dc3de">VirtualBox</a> <a href="/tags/Vsftpd/" style="font-size: 13px; color: #7dc3de">Vsftpd</a> <a href="/tags/jQuery/" style="font-size: 13px; color: #7dc3de">jQuery</a> <a href="/tags/pam-mysql/" style="font-size: 13px; color: #7dc3de">pam_mysql</a> <a href="/tags/小米/" style="font-size: 13px; color: #7dc3de">小米</a> <a href="/tags/软件/" style="font-size: 15.63px; color: #59bd8b">软件</a>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/09/">September 2015</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/08/">August 2015</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/07/">July 2015</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/05/">May 2015</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/04/">April 2015</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/03/">March 2015</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/02/">February 2015</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/12/">December 2014</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/11/">November 2014</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/10/">October 2014</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/09/">September 2014</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/08/">August 2014</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/07/">July 2014</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/06/">June 2014</a><span class="archive-list-count">6</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/05/">May 2014</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/04/">April 2014</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/03/">March 2014</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/02/">February 2014</a><span class="archive-list-count">11</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/01/">January 2014</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2013/12/">December 2013</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2013/11/">November 2013</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2013/08/">August 2013</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2013/07/">July 2013</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2013/06/">June 2013</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2013/05/">May 2013</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2013/04/">April 2013</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2012/03/">March 2012</a><span class="archive-list-count">1</span></li></ul>
    </div>
  </div>


  
    <div class="widget-wrap">
  <h3 class="widget-title">Calendar</h3>
  <div class="widget">
    <div id="g-calendar" class="g-calendar">
        <span class="g-calendar-prev"></span>
		 
        <span class="g-calendar-back"></span>
        <span class="g-calendar-now"></span>
		 
        <span class="g-calendar-next"></span>
        <div class="g-calendar-hd"></div>
        <div class="g-calendar-tit"></div>
        <div class="g-calendar-bd"></div>
    </div>
  </div>
</div>
<script type="text/javascript">
function LGY_calendar(wrapId, options){
    this.oWrap = this.getId(wrapId);
    this.oHead = this.getByClassName('g-calendar-hd',this.oWrap)[0];
    this.oBody = this.getByClassName('g-calendar-bd',this.oWrap)[0];
    this.oTit = this.getByClassName('g-calendar-tit',this.oWrap)[0];
    this.oPrev = this.getByClassName('g-calendar-prev',this.oWrap)[0];
    this.oNext = this.getByClassName('g-calendar-next',this.oWrap)[0];
    this.oNow = this.getByClassName('g-calendar-now',this.oWrap)[0];
    this.oBack = this.getByClassName('g-calendar-back',this.oWrap)[0];
    this.init();
}
LGY_calendar.prototype = {
    ///////////获取ID元素
    getId:function(id){
        return document.getElementById(id);
    },
    ////////获取css类名元素
    getByClassName:function(className,parent){
        var elem = [],
            node = parent != undefined&&parent.nodeType==1?parent.getElementsByTagName('*'):document.getElementsByTagName('*'),
            p = new RegExp("(^|\\s)"+className+"(\\s|$)");
        for(var n=0,i=node.length;n<i;n++){
            if(p.test(node[n].className)){
                elem.push(node[n]);
            }
        }
        return elem;
    },
    //填充日历
    fillDate:function(year,month){
        //本月份第一天是星期几-为显示上个月的天数做铺垫
        var first_day = new Date(year,month,1).getDay(),
        //如果刚好是星期天，则空出一行（显示上个月的天数）
            first_day = first_day == 0?first_day=7:first_day;
        //本月份最后一天是几号
        var final_date = new Date(year,month+1,0).getDate(),
        //上个月的最后一天是几号
            last_date = new Date(year,month,0).getDate(),
        //剩余的格子数--即排在末尾的格子数
            surplus = 42 - first_day - final_date;
        //设置年的链接
        var yearHead = "<a href='/" + "archives/" + year + "/'>" + year + " "+ "</a>"; 
        //设置年的链接
        var monthHead = "";
        var month1 = month + 1;
        if (month1 < 10) {
            monthHead = "<a href='/" + "archives/" + year + "/" + "0" + month1 + "/'>" + " " + month1 + " " + "</a>";
        } else {
            monthHead = "<a href='/" + "archives/" + year + "/" + month1 + "/'>" + " " + month1 + " " + "</a>";
        }
        //设置表头的日历
        this.oHead.innerHTML = yearHead+'年'+monthHead+'月';
        //填充日历执行
        var html = '';
        //上个月的显示天数
        for(var i=0;i<first_day;i++){
            html+='<span class="g-calendar-grey">'+(last_date-(first_day-1)+i)+'</span>';
        }
        //本月的显示天数
        var postdate = new Date("Thu Apr 30 2015 09:19:31 GMT+0800"); 
        if (true && postdate.getFullYear() == year && postdate.getMonth() == month) { 
            html += '<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span><a href="/2015/04/07/jvm-note-1/" title="深入理解Java虚拟机笔记一（Java内存区域与内存溢出异常）">7</a></span><span><a href="/2015/04/08/jvm-note-2/" title="深入理解Java虚拟机笔记二（垃圾收集器与内存分配策略）">8</a></span><span><a href="/2015/04/09/jvm-note-3/" title="深入理解Java虚拟机笔记三（JVM性能监控与故障处理工具）">9</a></span><span>10</span><span>11</span><span>12</span><span>13</span><span>14</span><span>15</span><span>16</span><span>17</span><span>18</span><span>19</span><span>20</span><span>21</span><span>22</span><span>23</span><span>24</span><span>25</span><span>26</span><span>27</span><span>28</span><span>29</span><span><a href="/2015/04/30/freemarker-template-development-note/" title="FreeMarker-模板开发笔记">30</a></span><span>31</span>';
        } else {
            for(var j=0;j<final_date;j++){        
                html+='<span id="d'+(j+1)+'">'+(j+1)+'</span>';
            }
        }
        //下个月的显示天数
        for(var k=0;k<surplus;k++){
            html+='<span class="g-calendar-grey">'+(k+1)+'</span>';
        }
        //fill
        this.oBody.innerHTML = html;
        // 当前状态
        if(year==this.c_year&&this.c_month==month){
            this.oBody.getElementsByTagName('span')[first_day+this.date-1].className='g-calendar-on';
        }

        // 对所有文章遍历,然后将有文章的日期加上链接,如果文章太多的话,生成页面会很大,去掉了
        
    },
    // next切换
    next:function(){
        var _that = this;
        this.oNext.onclick = function(){
            _that.month++;
            if(_that.month>11){
                _that.month = 0;
                _that.year++;
            }
            // 填充日历
            _that.fillDate(_that.year,_that.month);
        };
    },
    // back 切换
    back:function(){
        var _that = this;
        if(this.oBack != undefined) {
            this.oBack.onclick = function(){
                var postdate = new Date("Thu Apr 30 2015 09:19:31 GMT+0800"); 
                _that.year = postdate.getFullYear();
                _that.month = postdate.getMonth();
                // 填充日历
                _that.fillDate(_that.year,_that.month);
            };
        }
    },
    // now切换
    now:function(){
        var _that = this;
        if(this.oNow != undefined ) {
            this.oNow.onclick = function(){
                var nowDate = new Date(); 
                _that.year = nowDate.getFullYear();
                _that.month = nowDate.getMonth();
                // 填充日历
                _that.fillDate(_that.year,_that.month);
            };
        }
    },
    // prev切换
    prev:function(){
        var _that = this;
        this.oPrev.onclick = function(){
            _that.month--;
            if(_that.month<0){
                _that.month = 11;
                _that.year--;
            }
            // 填充日历
            _that.fillDate(_that.year,_that.month);
        };
    },
    init:function(){
        this.oTit.innerHTML = '<span>日</span><span>一</span><span>二</span><span>三</span><span>四</span><span>五</span><span>六</span>';
        // 获取今天的日历时间
        var now = new Date();
        this.c_year = this.year = now.getFullYear();
        this.c_month = this.month = now.getMonth();
        this.date = now.getDate();
        // 初始化--填充日历
        this.fillDate(this.year,this.month);
        //next切换
        this.next();
        //prev切换
        this.prev();
        //back 切换
        this.back();
        //now 切换
        this.now();
    }
}
new LGY_calendar('g-calendar');
</script>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2015/09/01/javascript-summary/">JavaScript 总结</a>
          </li>
        
          <li>
            <a href="/2015/08/28/javascript-oop-function-expression-and-async/">JavaScript 面向对象程序设计、函数表达式和异步编程</a>
          </li>
        
          <li>
            <a href="/2015/08/28/javascript-reference-type/">JavaScript 引用类型</a>
          </li>
        
          <li>
            <a href="/2015/08/28/javascript-grammar/">JavaScript 基本语法</a>
          </li>
        
          <li>
            <a href="/2015/08/10/java-web/">Java Web 笔记</a>
          </li>
        
      </ul>
    </div>
  </div>


  
    
<div class="widget-wrap">
  <h3 class="widget-title">Recent Comments</h3>
  <ul class="widget ds-recent-comments" data-num-items="5" data-show-avatars="0" data-show-title="1" data-show-time="1"></ul>
</div>
<!-- 需要多说的公用代码 -->


  

</aside>

        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2015 howiefh<br>
      Powered by <a href="http://zespia.tw/hexo/" target="_blank">Hexo</a> and Theme by <a href="https://github.com/howiefh/hexo-theme-landscape-f" target="_blank" title="Landscape-F">Landscape-F</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<!-- 多说公共JS代码 start (一个网页只需插入一次) -->

<script type="text/javascript">
  var duoshuoQuery = {short_name:"howiefh"};
  (function() {
	var ds = document.createElement('script');
	ds.type = 'text/javascript';ds.async = true;
	ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
	ds.charset = 'UTF-8';
	(document.getElementsByTagName('head')[0] 
		|| document.getElementsByTagName('body')[0]).appendChild(ds);
  })();
</script> 

<!-- 多说公共JS代码 end -->

<!-- 百度分享 start -->

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":["mshare","douban","bdysc","sqq","qq","hi","baidu","huaban","youdao","sdo","mail","xg","diandian","fx","copy","print"],"bdPic":"","bdStyle":"1","bdSize":"16"},"share":{},"image":{"viewList":["qzone","tsina","tqq","renren","weixin"],"viewText":"分享到：","viewSize":"16"}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>

<!-- 百度分享 end -->

<!--
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="/js/jquery.min.js"></script>
-->
<script src="/js/jquery.min.js" type="text/javascript"></script>


  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css" type="text/css">
  <script src="/fancybox/jquery.fancybox.pack.js" type="text/javascript"></script>


<div class="bottom-btn">

	<a class="icon-gotop" href="javascript:void(0)" title="返回顶部"></a>
	<script src="/js/gotop.js" type="text/javascript"></script>
	<!--
	<script src="/js/gotop.js"></script>
	-->


	<a class="icon-toc-toggle" href="javascript:void(0)" title="文章目录"></a>
	<!--
	<script src="/js/toc_aside_toggle.js"></script>
	-->

</div>
<script src="/js/toc_aside_toggle.js" type="text/javascript"></script>


<script src="/js/script.js" type="text/javascript"></script>

  </div>
</body>
</html>
